home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / game / shoot / ADescentSrc.lha / descent / main / automap.c < prev    next >
C/C++ Source or Header  |  1999-03-18  |  34KB  |  1,226 lines

  1. /*
  2. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  3. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  4. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  5. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  6. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  7. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  8. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  9. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  10. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
  11. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  12. */
  13. /*
  14.  * $Source: /usr/CVS/descent/main/automap.c,v $
  15.  * $Revision: 1.9 $
  16.  * $Author: tfrieden $
  17.  * $Date: 1998/04/24 14:26:38 $
  18.  * 
  19.  * Routines for displaying the auto-map.
  20.  * 
  21.  * $Log: automap.c,v $
  22.  * Revision 1.9  1998/04/24 14:26:38  tfrieden
  23.  * Bugfixes
  24.  *
  25.  * Revision 1.8  1998/04/09 17:15:23  hfrieden
  26.  * Added new automapper stuff for ViRGE
  27.  *
  28.  * Revision 1.7  1998/04/02 13:43:27  tfrieden
  29.  * Raised edge limit
  30.  *
  31.  * Revision 1.6  1998/03/30 18:40:42  hfrieden
  32.  * New hardware-accelerated Automapper for ViRGE
  33.  *
  34.  * Revision 1.5  1998/03/29 21:22:23  tfrieden
  35.  * Made automap work for real now
  36.  *
  37.  * Revision 1.4  1998/03/25 22:01:54  tfrieden
  38.  * Inserted a clear_canvas, which doesn`t seem to work :)
  39.  *
  40.  * Revision 1.3  1998/03/22 21:47:43  tfrieden
  41.  * Cleared background on automapper
  42.  *
  43.  * Revision 1.2  1998/03/15 01:22:26  nobody
  44.  * Removed the automap ackground => works now
  45.  *
  46.  * Revision 1.1.1.1  1998/03/03 15:12:13  nobody
  47.  * reimport after crash from backup
  48.  *
  49.  * Revision 1.2  1998/02/28 00:50:04  tfrieden
  50.  * aga support
  51.  *
  52.  * Revision 1.1.1.1  1998/02/13  20:20:39  hfrieden
  53.  * Initial Import
  54.  */
  55.  
  56.  
  57. #pragma off (unreferenced)
  58. static char rcsid[] = "$Id: automap.c,v 1.9 1998/04/24 14:26:38 tfrieden Exp $";
  59. #pragma on (unreferenced)
  60.  
  61. #include <stdio.h>
  62. #include <stdlib.h>
  63. #include <string.h>
  64. #include <math.h>
  65. #include <bsd/bsd.h>
  66.  
  67. #include "error.h"
  68. #include "3d.h"
  69. #include "inferno.h"
  70. #include "mem.h"
  71. #include "render.h"
  72. #include "object.h"
  73. #include "vclip.h"
  74. #include "game.h"
  75. #include "mono.h"
  76. #include "polyobj.h"
  77. #include "sounds.h"
  78. #include "player.h"
  79. #include "bm.h"
  80. #include "key.h"
  81. #include "screens.h"
  82. #include "textures.h"
  83. #include "mouse.h"
  84. #include "timer.h"
  85. #include "segpoint.h"
  86. #include "joy.h"
  87. #include "iff.h"
  88. #include "pcx.h"
  89. #include "palette.h"
  90. #include "wall.h"
  91. #include "hostage.h"
  92. #include "fuelcen.h"
  93. #include "gameseq.h"
  94. #include "gamefont.h"
  95. #include "network.h"
  96. #include "kconfig.h"
  97. #include "multi.h"
  98. #include "endlevel.h"
  99. #include "text.h"
  100. #include "gauges.h"
  101. #include "powerup.h"
  102. #include "network.h" 
  103.  
  104. #ifdef VIRGIN
  105. #include <exec/types.h>
  106. #include <cybergraphics/cybergraphics.h>
  107. #include <inline/cybergraphics.h>
  108. #include <cybergraphics/cgx3dvirgin.h>
  109. #include <clib/cgx3dvirgin_protos.h>
  110. #include <inline/cgx3dvirgin.h>
  111. #include "VirgeTexture.h"
  112. extern View3D MyView;
  113. extern struct Library *CGX3DVirginBase;
  114. #define g3_draw_line g3_direct_draw_line
  115. #define g3_draw_sphere g3_direct_draw_sphere
  116. #define gr_bitmapm gr_direct_bitmapm
  117. #define gr_printf gr_direct_printf
  118. int __height;
  119. int __width;
  120. #endif
  121.  
  122. #define EF_USED         1       // This edge is used
  123. #define EF_DEFINING     2       // A structure defining edge that should always draw.
  124. #define EF_FRONTIER     4       // An edge between the known and the unknown.
  125. #define EF_SECRET           8       // An edge that is part of a secret wall.
  126. #define EF_GRATE            16      // A grate... draw it all the time.
  127. #define EF_NO_FADE      32      // An edge that doesn't fade with distance
  128. #define EF_TOO_FAR      64      // An edge that is too far away
  129.  
  130. typedef struct Edge_info {
  131.     union {
  132.         short verts[2];     // 4 bytes
  133.         int vv;
  134.     } moo;
  135.     ubyte sides[4];         // 4 bytes
  136.     short segnum[4];            // 8 bytes  // This might not need to be stored... If you can access the normals of a side.
  137.     ubyte flags;                // 1 bytes  // See the EF_??? defines above.
  138.     ubyte color;                // 1 bytes
  139.     ubyte num_faces;            // 1 bytes  // 19 bytes...
  140. } Edge_info;
  141.  
  142. //OLD BUT GOOD -- #define MAX_EDGES_FROM_VERTS(v)   ((v*5)/2)
  143. // THE following was determined by John by loading levels 1-14 and recording
  144. // numbers on 10/26/94. 
  145. //#define MAX_EDGES_FROM_VERTS(v)   (((v)*21)/10)
  146. #define MAX_EDGES_FROM_VERTS(v)     ((v)*8)
  147. //#define MAX_EDGES (MAX_EDGES_FROM_VERTS(MAX_VERTICES))
  148.  
  149. #define MAX_EDGES 15000      // Determined by loading all the levels by John & Mike, Feb 9, 1995
  150.  
  151. #define WALL_NORMAL_COLOR               BM_XRGB( 29, 29, 29 )
  152. #define WALL_DOOR_COLOR                 BM_XRGB( 21, 31, 11 )
  153. #define WALL_DOOR_BLUE                      BM_XRGB( 0, 0, 31)
  154. #define WALL_DOOR_GOLD                      BM_XRGB( 31, 31, 0)
  155. #define WALL_DOOR_RED                       BM_XRGB( 31, 0, 0)
  156.  
  157. // Segment visited list
  158. ubyte Automap_visited[MAX_SEGMENTS];
  159.  
  160. // Edge list variables
  161. static int Num_edges=0;
  162. static int Max_edges;       //set each frame
  163. static int Highest_edge_index = -1;
  164. static Edge_info Edges[MAX_EDGES];
  165. static short DrawingListBright[MAX_EDGES];
  166. int automap_abort = 0;
  167.  
  168. //static short DrawingListBright[MAX_EDGES];
  169. //static short Edge_used_list[MAX_EDGES];               //which entries in edge_list have been used
  170.  
  171. // Map movement defines
  172. #define PITCH_DEFAULT 9000
  173. #define ZOOM_DEFAULT i2f(20*10)
  174. #define ZOOM_MIN_VALUE i2f(20*5)
  175. #define ZOOM_MAX_VALUE i2f(20*100)
  176.  
  177. #define SLIDE_SPEED                 (350)
  178. #define ZOOM_SPEED_FACTOR       (1500)
  179. #define ROT_SPEED_DIVISOR       (115000)
  180.  
  181. // Screen anvas variables
  182. static int current_page=0;
  183. static grs_canvas Pages[2];
  184. static grs_canvas DrawingPages[2];
  185.  
  186. // Flags
  187. static int Automap_cheat = 0;       // If set, show everything
  188. extern int Automap_large_screen;    // If set to 1, open automap in 640x480
  189.  
  190. // Rendering variables
  191. static fix Automap_zoom = 0x9000;
  192. static vms_vector view_target;
  193. static fix Automap_farthest_dist = (F1_0 * 20 * 50);        // 50 segments away
  194. static vms_matrix   ViewMatrix;
  195. static fix ViewDist=0;
  196.  
  197. void adjust_segment_limit(int SegmentLimit);
  198. void draw_all_edges();
  199. void automap_build_edge_list();
  200.  
  201.  
  202. void automap_clear_visited()    
  203. {
  204.     int i;
  205.     for (i=0; i<MAX_SEGMENTS; i++ )
  206.         Automap_visited[i] = 0;
  207. }
  208.  
  209. grs_canvas *name_canv;
  210.  
  211. void draw_player( object * obj )
  212. {
  213.     vms_vector arrow_pos, head_pos;
  214.     g3s_point sphere_point, arrow_point, head_point;
  215.  
  216.     // Draw Console player -- shaped like a ellipse with an arrow.
  217.     g3_rotate_point(&sphere_point,&obj->pos);
  218.     g3_draw_sphere(&sphere_point,obj->size);
  219.  
  220.     // Draw shaft of arrow
  221.     vm_vec_scale_add( &arrow_pos, &obj->pos, &obj->orient.fvec, obj->size*3 );
  222.     g3_rotate_point(&arrow_point,&arrow_pos);
  223.     g3_draw_line( &sphere_point, &arrow_point );
  224.  
  225.     // Draw right head of arrow
  226.     vm_vec_scale_add( &head_pos, &obj->pos, &obj->orient.fvec, obj->size*2 );
  227.     vm_vec_scale_add2( &head_pos, &obj->orient.rvec, obj->size*1 );
  228.     g3_rotate_point(&head_point,&head_pos);
  229.     g3_draw_line( &arrow_point, &head_point );
  230.  
  231.     // Draw left head of arrow
  232.     vm_vec_scale_add( &head_pos, &obj->pos, &obj->orient.fvec, obj->size*2 );
  233.     vm_vec_scale_add2( &head_pos, &obj->orient.rvec, obj->size*(-1) );
  234.     g3_rotate_point(&head_point,&head_pos);
  235.     g3_draw_line( &arrow_point, &head_point );
  236.  
  237.     // Draw player's up vector
  238.     vm_vec_scale_add( &arrow_pos, &obj->pos, &obj->orient.uvec, obj->size*2 );
  239.     g3_rotate_point(&arrow_point,&arrow_pos);
  240.     g3_draw_line( &sphere_point, &arrow_point );
  241. }
  242.  
  243.  
  244. void draw_automap()
  245. {
  246.     int i;
  247.     int color;
  248.     object * objp;
  249.     vms_vector viewer_position;
  250.     g3s_point sphere_point;
  251.     #ifdef VIRGIN
  252.     static short automap_color1 = -1;
  253.     static short automap_color2 = -1;
  254.     char namebuf[128];
  255.     extern void virge_repw(UWORD *start __asm("a0"), int num __asm("d0"), UWORD data __asm("d1"));
  256.     UWORD *RenderBuffer = (UWORD *)VirgeGetBuffer();
  257.     extern int VirgePixelsPerRow;
  258.     int step, yy;
  259.     #endif
  260.  
  261. //    current_page ^= 1;
  262.     gr_set_current_canvas(&DrawingPages[current_page]);
  263.  
  264.     g3_start_frame();
  265.     #ifdef VIRGIN
  266.     if (V3D_LockView(MyView)) {
  267.         VirgeClearBuffer();
  268.         V3D_UnLockView(MyView);
  269.     }
  270.     step = __height/8;
  271.     yy = step;
  272.     while (yy<__height) {
  273.         virge_repw(RenderBuffer+yy*VirgePixelsPerRow, __width, 0x00e0);
  274.         yy+=step;
  275.     }
  276.     #endif
  277.     render_start_frame();
  278.     
  279.     vm_vec_scale_add(&viewer_position,&view_target,&ViewMatrix.fvec,-ViewDist );
  280.  
  281.     g3_set_view_matrix(&viewer_position,&ViewMatrix,Automap_zoom);
  282.  
  283.     #ifndef VIRGIN
  284.     gr_clear_canvas(0);
  285.     #endif
  286.     draw_all_edges();
  287.  
  288.     // Draw player...
  289. #ifdef NETWORK
  290.     if (Game_mode & GM_TEAM)
  291.         color = get_team(Player_num);
  292.     else
  293. #endif  
  294.         color = Player_num; // Note link to above if!
  295.     gr_setcolor(gr_getcolor(player_rgb[color].r,player_rgb[color].g,player_rgb[color].b));
  296.     draw_player(&Objects[Players[Player_num].objnum]);
  297.                 
  298.     // Draw player(s)...
  299. #ifdef NETWORK
  300.     if ( (Game_mode & (GM_TEAM | GM_MULTI_COOP)) || (Netgame.game_flags & NETGAME_FLAG_SHOW_MAP) )  {
  301.         for (i=0; i<N_players; i++)     {
  302.             if ( (i != Player_num) && ((Game_mode & GM_MULTI_COOP) || (get_team(Player_num) == get_team(i)) || (Netgame.game_flags & NETGAME_FLAG_SHOW_MAP)) )  {
  303.                 if ( Objects[Players[i].objnum].type == OBJ_PLAYER )    {
  304.                     if (Game_mode & GM_TEAM)
  305.                         color = get_team(i);
  306.                     else
  307.                         color = i;
  308.                     gr_setcolor(gr_getcolor(player_rgb[color].r,player_rgb[color].g,player_rgb[color].b));
  309.                     draw_player(&Objects[Players[i].objnum]);
  310.                 }
  311.             }
  312.         }
  313.     }
  314. #endif
  315.  
  316.     objp = &Objects[0];
  317.     for (i=0;i<=Highest_object_index;i++,objp++) {
  318.         switch( objp->type )    {
  319.         case OBJ_HOSTAGE:
  320.             gr_setcolor(BM_XRGB(0,31,0));
  321.             g3_rotate_point(&sphere_point,&objp->pos);
  322.             g3_draw_sphere(&sphere_point,objp->size);   
  323.             break;
  324.         case OBJ_POWERUP:
  325.             if ( Automap_visited[objp->segnum] )    {
  326.                 if ( (objp->id==POW_KEY_RED) || (objp->id==POW_KEY_BLUE) || (objp->id==POW_KEY_GOLD) )  {
  327.                     switch (objp->id) {
  328.                     case POW_KEY_RED:       gr_setcolor(gr_getcolor(63, 5, 5)); break;
  329.                     case POW_KEY_BLUE:  gr_setcolor(gr_getcolor(5, 5, 63)); break;
  330.                     case POW_KEY_GOLD:  gr_setcolor(gr_getcolor(63, 63, 10)); break;
  331.                     }
  332.                     g3_rotate_point(&sphere_point,&objp->pos);
  333.                     g3_draw_sphere(&sphere_point,objp->size*4); 
  334.                 }
  335.             }
  336.             break;
  337.         }
  338.     }
  339.  
  340.     g3_end_frame();
  341.     #ifndef VIRGIN
  342.     gr_bitmapm(5,5,&name_canv->cv_bitmap);
  343.     #endif
  344.     #ifdef VIRGIN
  345.     if (automap_color1 == -1)
  346.         automap_color1 = BM_XRGB(0,20,0);
  347.  
  348.     if (automap_color2 == -1)
  349.         automap_color2 = BM_XRGB(0,0,40);
  350.  
  351.     gr_set_fontcolor(automap_color1, -1);
  352.     sprintf(namebuf, "%s %i: ",TXT_LEVEL, Current_level_num);
  353.     strcat(namebuf, Current_level_name);
  354.     gr_direct_printf( 40, 40,namebuf);
  355.     gr_direct_printf( 40, 22,TXT_AUTOMAP);
  356.     gr_set_fontcolor(automap_color2, -1);
  357.     gr_direct_printf( 40, __height-30,TXT_TURN_SHIP);
  358.     gr_direct_printf( 40, __height-20,TXT_SLIDE_UPDOWN);
  359.     gr_direct_printf( 40, __height-10,TXT_VIEWING_DISTANCE);
  360.     VirgeSwitchBuffer();
  361.     #else
  362.     gr_show_canvas( &Pages[current_page] );
  363.     #endif
  364. }
  365.  
  366. #define LEAVE_TIME 0x4000
  367.  
  368. //print to canvas & double height
  369. grs_canvas *print_to_canvas(char *s,grs_font *font, int fc, int bc)
  370. {
  371.     int y;
  372.     ubyte *data;
  373.     int rs;
  374.     grs_canvas *temp_canv,*save_canv;
  375.  
  376.     save_canv = grd_curcanv;
  377.  
  378.     temp_canv = gr_create_canvas(font->ft_w*strlen(s),font->ft_h*2);
  379.  
  380.     gr_set_current_canvas(temp_canv);
  381.     gr_set_curfont(font);
  382.     gr_clear_canvas(TRANSPARENCY_COLOR);                       //trans color
  383.     gr_set_fontcolor(fc,bc);
  384.     gr_printf(0,0,s);
  385.  
  386.     //now double it, since we're drawing to 400-line modex screen
  387.  
  388.     data = temp_canv->cv_bitmap.bm_data;
  389.     rs = temp_canv->cv_bitmap.bm_rowsize;
  390.  
  391.     for (y=temp_canv->cv_bitmap.bm_h/2;y--;) {
  392.         memcpy(data+(rs*y*2),data+(rs*y),temp_canv->cv_bitmap.bm_w);
  393.         memcpy(data+(rs*(y*2+1)),data+(rs*y),temp_canv->cv_bitmap.bm_w);
  394.     }
  395.  
  396.     gr_set_current_canvas(save_canv);
  397.  
  398.     return temp_canv;
  399. }
  400.  
  401. //print to buffer, double heights, and blit bitmap to screen
  402. modex_printf(int x,int y,char *s,int fontnum)
  403. {
  404.     grs_canvas *temp_canv;
  405.  
  406.     temp_canv = print_to_canvas(s,Gamefonts[fontnum], BM_XRGB(20,20,20), -1);
  407.  
  408.     gr_bitmapm(x,y,&temp_canv->cv_bitmap);
  409.  
  410.     gr_free_canvas(temp_canv);
  411. }
  412.  
  413. create_name_canv()
  414. {
  415.     char    name_level[128];
  416. #ifdef VIRGIN
  417.     return;
  418. #endif
  419.     if (Current_level_num > 0)
  420.         sprintf(name_level, "%s %i: ",TXT_LEVEL, Current_level_num);
  421.     else
  422.         name_level[0] = 0;
  423.  
  424.     strcat(name_level, Current_level_name);
  425.  
  426.     gr_set_fontcolor(BM_XRGB(0,31,0),-1);
  427.     name_canv = print_to_canvas(name_level,Gamefonts[GFONT_SMALL], BM_XRGB(0,31,0), -1);
  428.  
  429. }
  430.  
  431. void modex_print_message(int x, int y, char *str)
  432. {
  433.     int i;
  434.  
  435. //    for (i=0; i<2; i++ )    {
  436.     { i = 0;
  437.         gr_set_current_canvas(&Pages[i]);
  438.         modex_printf(x, y, str, GFONT_MEDIUM_1);
  439.     }
  440.  
  441.     gr_set_current_canvas(&DrawingPages[current_page]);
  442. }
  443.  
  444. extern void GameLoop(int, int );
  445. extern int set_segment_depths(int start_seg, ubyte *segbuf);
  446. extern int gr_keep_resolution;
  447. extern int VR_screen_mode;
  448. extern int VR_render_width;
  449. extern int VR_render_height;
  450. #ifdef WARP3D
  451. extern int WARP_automap_active;
  452. #endif
  453.  
  454. void do_automap( int key_code )
  455. {
  456.     int done=0;
  457.     vms_matrix  tempm;
  458.     vms_angvec  tangles;
  459.     int leave_mode=0;
  460.     int first_time=1;
  461.     int pcx_error;
  462.     int i;
  463.     int c;
  464.     char filename[] = "MAP.PCX";
  465.     fix entry_time;
  466.     int pause_game=1;       // Set to 1 if everything is paused during automap...No pause during net.
  467.     fix t1, t2;
  468.     control_info saved_control_info;
  469.     grs_bitmap Automap_background;
  470.     int Max_segments_away = 0;
  471.     int SegmentLimit = 1;
  472.     int width, height, mode;
  473.  
  474.     key_code = key_code;    // disable warning...
  475.  
  476.     if (gr_keep_resolution) {
  477.         mode = VR_screen_mode;
  478.         width = VR_render_width;
  479.         height = VR_render_height;
  480.         #ifdef WARP3D
  481.         WARP_automap_active = 1;
  482.         #endif
  483.     } else {
  484.         if (Automap_large_screen == 0) {
  485.             width = 320;
  486.             height = 400;
  487.             #ifdef VIRGIN
  488.             __width = 320;
  489.             __height=400;
  490.             #endif
  491.             mode = SM_320x400U;
  492.         } else {
  493.             width = 640;
  494.             height = 480;
  495.             #ifdef VIRGIN
  496.             __width = 640;
  497.             __height=480;
  498.             #endif
  499.             mode = SM_640x480V;
  500.         }
  501.     }
  502.  
  503.     //printf("Starting automap\n");
  504.  
  505.     gr_set_mode( mode );
  506.  
  507.     gr_palette_clear();
  508.  
  509.     if ((Game_mode & GM_MULTI) && (Function_mode == FMODE_GAME) && (!Endlevel_sequence))
  510.         pause_game = 0;
  511.  
  512.     if (pause_game)
  513.         stop_time();
  514.  
  515.     create_name_canv();
  516.  
  517.     Max_edges = min(MAX_EDGES_FROM_VERTS(Num_vertices),MAX_EDGES);          //make maybe smaller than max
  518.     //Edges = malloc( sizeof(Edge_info)*Max_edges);
  519.     //if ( Edges == NULL )  {
  520.     //  mprintf((0, "Couldn't get %dK for automap!", sizeof(Edge_info)*Max_edges/1024));
  521.     //  return;
  522.     //}
  523.     //DrawingListBright = malloc( sizeof(short)*Max_edges);
  524.     //if ( DrawingListBright == NULL )  {
  525.     //  mprintf((0, "Couldn't get %dK for automap!", sizeof(short)*Max_edges/1024));
  526.     //  return;
  527.     //}
  528.  
  529.     //printf( "Num_vertices=%d, Max_edges=%d, (MAX:%d)\n", Num_vertices, Max_edges, MAX_EDGES );
  530.     //printf( "Allocated %d K for automap edge list\n", (sizeof(Edge_info)+sizeof(short))*Max_edges/1024 );
  531.  
  532.  
  533.     //printf("Mode set\n");
  534.  
  535.     gr_init_sub_canvas(&Pages[0],grd_curcanv,0,0,width,height);                 //printf("1"); fflush(stdout);
  536. //    gr_init_sub_canvas(&Pages[1],grd_curcanv,0,height+1,width,height);          printf("...2"); fflush(stdout);
  537. #ifdef VIRGIN
  538.     gr_init_sub_canvas(&DrawingPages[0],&Pages[0],16,69,width,height);
  539. //    gr_init_sub_canvas(&DrawingPages[1],&Pages[1],16,69,width,height);
  540. #else
  541.     gr_init_sub_canvas(&DrawingPages[0],&Pages[0],16,69,width-32,height-128);   //printf("...3");fflush(stdout);
  542. //    gr_init_sub_canvas(&DrawingPages[1],&Pages[1],16,69,width-32,height-128);   printf("...4");fflush(stdout);
  543. #endif
  544.     Automap_background.bm_data = NULL;
  545.     gr_clear_canvas(0);                                                         //printf("...5\n");fflush(stdout);
  546.  
  547. /*    if (!Automap_large_screen) {
  548.         pcx_error = pcx_read_bitmap(filename,&Automap_background,BM_LINEAR,NULL);
  549.         if ( pcx_error != PCX_ERROR_NONE )  {
  550.             printf("File %s - PCX error: %s",filename,pcx_errormsg(pcx_error));
  551.             Error("File %s - PCX error: %s",filename,pcx_errormsg(pcx_error));
  552.             return;
  553.         }
  554.     }   */
  555. #ifndef VIRGIN
  556. //    for (i=0; i<2; i++ )    {
  557.     { i = 0;
  558.         gr_set_current_canvas(&Pages[i]);                                       //printf("a..."); fflush(stdout);
  559.         modex_printf( 40, 22,TXT_AUTOMAP,GFONT_BIG_1);                          //printf("b..."); fflush(stdout);
  560.         modex_printf( 70,height-47,TXT_TURN_SHIP,GFONT_SMALL);                  //printf("c..."); fflush(stdout);
  561.         modex_printf( 70,height-31,TXT_SLIDE_UPDOWN,GFONT_SMALL);               //printf("d..."); fflush(stdout);
  562.         modex_printf( 70,height-15,TXT_VIEWING_DISTANCE,GFONT_SMALL);           //printf("e\n");  fflush(stdout);
  563.     }
  564. //    gr_update(NULL);
  565. #endif
  566.     //printf("Stuff painted\n");
  567.  
  568. /*    if (!Automap_large_screen) {
  569.         if ( Automap_background.bm_data )
  570.             free( Automap_background.bm_data );
  571.     }*/
  572.     Automap_background.bm_data = NULL;
  573.  
  574.     gr_set_current_canvas(&DrawingPages[current_page]);
  575.  
  576.     automap_build_edge_list();
  577.     //printf("Built edge list\n");
  578.  
  579.     if ( ViewDist==0 ) 
  580.         ViewDist = ZOOM_DEFAULT;
  581.     ViewMatrix = Objects[Players[Player_num].objnum].orient;
  582.  
  583.     tangles.p = PITCH_DEFAULT;
  584.     tangles.h  = 0;
  585.     tangles.b  = 0;
  586.  
  587.     done = 0;
  588.  
  589.     view_target = Objects[Players[Player_num].objnum].pos;
  590.  
  591.     t1 = entry_time = timer_get_fixed_seconds();
  592.     t2 = t1;
  593.  
  594.     //Fill in Automap_visited from Objects[Players[Player_num].objnum].segnum
  595.     Max_segments_away = set_segment_depths(Objects[Players[Player_num].objnum].segnum, Automap_visited);
  596.     SegmentLimit = Max_segments_away;
  597.  
  598.     //printf("adjusted segment linit\n");
  599.     adjust_segment_limit(SegmentLimit);
  600.  
  601.     //printf("Going into main loop\n");
  602.  
  603.     while(!done && automap_abort == 0)    {
  604.         if ( leave_mode==0 && Controls.automap_state && (timer_get_fixed_seconds()-entry_time)>LEAVE_TIME)
  605.             leave_mode = 1;
  606.         //printf("1");fflush(stdout);
  607.         if ( !Controls.automap_state && (leave_mode==1) )
  608.             done=1;
  609.  
  610.         if (!pause_game)    {
  611.             ushort old_wiggle;
  612.             saved_control_info = Controls;              // Save controls so we can zero them
  613.             memset(&Controls,0,sizeof(control_info));   // Clear everything...
  614.             old_wiggle = ConsoleObject->mtype.phys_info.flags & PF_WIGGLE;  // Save old wiggle
  615.             ConsoleObject->mtype.phys_info.flags &= ~PF_WIGGLE;     // Turn off wiggle
  616.             #ifdef NETWORK
  617.             if (multi_menu_poll())
  618.                 done = 1;
  619.             #endif
  620. //          GameLoop( 0, 0 );       // Do game loop with no rendering and no reading controls.
  621.             ConsoleObject->mtype.phys_info.flags |= old_wiggle; // Restore wiggle
  622.             Controls = saved_control_info;
  623.         } 
  624.         //printf("2");fflush(stdout);
  625.         controls_read_all();        
  626.         if ( Controls.automap_down_count )  {
  627.             if (leave_mode==0)
  628.                 done = 1;
  629.             c = 0;
  630.         }
  631.  
  632.         //printf("3");fflush(stdout);
  633.  
  634.         while( (c=key_inkey()) )    {
  635.             switch( c ) {
  636.             #ifndef NDEBUG
  637.             case KEY_BACKSP: Int3(); break;
  638.             #endif
  639.     
  640.             case KEY_PRINT_SCREEN: save_screen_shot(1); break;
  641.     
  642.             case KEY_ESC:
  643.                 if (leave_mode==0)
  644.             case KEY_ALTED+KEY_F:       // Alt+F shows full map, if cheats enabled
  645.                 if (Cheats_enabled) 
  646.                 {
  647.                     uint t; 
  648.                     t = Players[Player_num].flags;
  649.                     Players[Player_num].flags |= PLAYER_FLAGS_MAP_ALL_CHEAT;
  650.                     automap_build_edge_list();
  651.                     Players[Player_num].flags=t;
  652.                 }
  653.                 break;
  654.     
  655.     #ifndef NDEBUG
  656.             case KEY_DEBUGGED+KEY_F:    {
  657.                 for (i=0; i<=Highest_segment_index; i++ )
  658.                     Automap_visited[i] = 1;
  659.                 automap_build_edge_list();
  660.                 Max_segments_away = set_segment_depths(Objects[Players[Player_num].objnum].segnum, Automap_visited);
  661.                 SegmentLimit = Max_segments_away;
  662.                 adjust_segment_limit(SegmentLimit);
  663.                 }
  664.                 break;
  665.     #endif
  666.             case KEY_MINUS:
  667.                 if (SegmentLimit > 1)       {
  668.                     SegmentLimit--;
  669.                     adjust_segment_limit(SegmentLimit);
  670.                 }
  671.                 break;
  672.             case KEY_EQUAL:
  673.                 if (SegmentLimit < Max_segments_away)   {
  674.                     SegmentLimit++;
  675.                     adjust_segment_limit(SegmentLimit);
  676.                 }
  677.                 break;
  678.             }
  679.         }
  680.         //printf("4");fflush(stdout);
  681.         if ( Controls.fire_primary_down_count ) {
  682.             // Reset orientation
  683.             ViewDist = ZOOM_DEFAULT;
  684.             tangles.p = PITCH_DEFAULT;
  685.             tangles.h  = 0;
  686.             tangles.b  = 0;
  687.             view_target = Objects[Players[Player_num].objnum].pos;
  688.         }
  689.  
  690.         ViewDist -= Controls.forward_thrust_time*ZOOM_SPEED_FACTOR;
  691.  
  692.         tangles.p += fixdiv( Controls.pitch_time, ROT_SPEED_DIVISOR );
  693.         tangles.h  += fixdiv( Controls.heading_time, ROT_SPEED_DIVISOR );
  694.         tangles.b  += fixdiv( Controls.bank_time, ROT_SPEED_DIVISOR*2 );
  695.         //printf("5");fflush(stdout);
  696.         if ( Controls.vertical_thrust_time || Controls.sideways_thrust_time )   {
  697.             vms_angvec  tangles1;
  698.             vms_vector  old_vt;
  699.             old_vt = view_target;
  700.             tangles1 = tangles;
  701.             vm_angles_2_matrix(&tempm,&tangles1);
  702.             vm_matrix_x_matrix(&ViewMatrix,&Objects[Players[Player_num].objnum].orient,&tempm);
  703.             vm_vec_scale_add2( &view_target, &ViewMatrix.uvec, Controls.vertical_thrust_time*SLIDE_SPEED );
  704.             vm_vec_scale_add2( &view_target, &ViewMatrix.rvec, Controls.sideways_thrust_time*SLIDE_SPEED );
  705.             if ( vm_vec_dist_quick( &view_target, &Objects[Players[Player_num].objnum].pos) > i2f(1000) )   {
  706.                 view_target = old_vt;
  707.             }
  708.         } 
  709.         //printf("6");fflush(stdout);
  710.         vm_angles_2_matrix(&tempm,&tangles);
  711.         vm_matrix_x_matrix(&ViewMatrix,&Objects[Players[Player_num].objnum].orient,&tempm);
  712.  
  713.         if ( ViewDist < ZOOM_MIN_VALUE ) ViewDist = ZOOM_MIN_VALUE;
  714.         if ( ViewDist > ZOOM_MAX_VALUE ) ViewDist = ZOOM_MAX_VALUE;
  715.         draw_automap();
  716.         //printf("7");fflush(stdout);
  717.         if ( first_time )   {
  718.             first_time = 0;
  719.             gr_palette_load( gr_palette );
  720.         }
  721.         //printf("8");fflush(stdout);
  722.     #if !defined(VIRGIN) && !defined(WARP3D)
  723.         gr_update(NULL);
  724.     #endif
  725.         t2 = timer_get_fixed_seconds();
  726.         if (pause_game)
  727.             FrameTime=t2-t1;
  728.         t1 = t2;
  729.         //printf("9\n");
  730.     }
  731.  
  732.     //printf("\nDone\n");
  733.  
  734.     automap_abort = 0;
  735.  
  736.     //free(Edges);
  737.     //free(DrawingListBright);
  738.     #ifndef VIRGIN
  739.     gr_free_canvas(name_canv);  name_canv=NULL;
  740.     #endif
  741.  
  742.     mprintf( (0, "Automap memory freed\n" ));
  743.  
  744.     game_flush_inputs();
  745.  
  746.     if (pause_game)
  747.         start_time();
  748.  
  749. //    gr_set_mode( SM_320x200x8 );
  750.     gr_set_mode(VR_screen_mode);
  751.  
  752.     #ifdef WARP3D
  753.     WARP_automap_active = 0;
  754.     #endif
  755.  
  756. }
  757.  
  758. void adjust_segment_limit(int SegmentLimit)
  759. {
  760.     int i,e1;
  761.     Edge_info * e;
  762.  
  763.     mprintf(( 0, "Seglimit: %d\n", SegmentLimit ));
  764.     
  765.     for (i=0; i<=Highest_edge_index; i++ )  {
  766.         e = &Edges[i];
  767.         e->flags |= EF_TOO_FAR;
  768.         for (e1=0; e1<e->num_faces; e1++ )  {
  769.             if ( Automap_visited[e->segnum[e1]] <= SegmentLimit )   {
  770.                 e->flags &= (~EF_TOO_FAR);
  771.                 break;
  772.             }
  773.         }
  774.     }
  775.     
  776. }
  777.  
  778. void draw_all_edges()   
  779. {
  780.     g3s_codes cc;
  781.     int i,j,nbright;
  782.     ubyte nfacing,nnfacing;
  783.     Edge_info *e;
  784.     vms_vector *tv1;
  785.     fix distance;
  786.     fix min_distance = 0x7fffffff;
  787.     g3s_point *p1, *p2;
  788.     
  789.     
  790.     nbright=0;
  791.  
  792.     for (i=0; i<=Highest_edge_index; i++ )  {
  793.         //e = &Edges[Edge_used_list[i]];
  794.         e = &Edges[i];
  795.         if (!(e->flags & EF_USED)) continue;
  796.  
  797.         if ( e->flags & EF_TOO_FAR) continue;
  798.  
  799.         if (e->flags&EF_FRONTIER)   {                       // A line that is between what we have seen and what we haven't
  800.             if ( (!(e->flags&EF_SECRET))&&(e->color==WALL_NORMAL_COLOR))
  801.                 continue;       // If a line isn't secret and is normal color, then don't draw it
  802.         }
  803.  
  804.         cc=rotate_list(2,e->moo.verts);
  805.         distance = Segment_points[e->moo.verts[1]].p3_vec.z;
  806.  
  807.         if (min_distance>distance )
  808.             min_distance = distance;
  809.  
  810.         if (!cc.and)    {   //all off screen?
  811.             nfacing = nnfacing = 0;
  812.             tv1 = &Vertices[e->moo.verts[0]];
  813.             j = 0;
  814.             while( j<e->num_faces && (nfacing==0 || nnfacing==0) )  {
  815.                 #ifdef COMPACT_SEGS
  816.                 vms_vector temp_v;
  817.                 get_side_normal(&Segments[e->segnum[j]], e->sides[j], 0, &temp_v );
  818.                 if (!g3_check_normal_facing( tv1, &temp_v ) )
  819.                 #else
  820.                 if (!g3_check_normal_facing( tv1, &Segments[e->segnum[j]].sides[e->sides[j]].normals[0] ) )
  821.                 #endif
  822.                     nfacing++;
  823.                 else
  824.                     nnfacing++;
  825.                 j++;
  826.             }
  827.  
  828.             if ( nfacing && nnfacing )  {
  829.                 // a contour line
  830.                 DrawingListBright[nbright++] = e-Edges;
  831.             } else if ( e->flags&(EF_DEFINING|EF_GRATE) )   {
  832.                 if ( nfacing == 0 ) {
  833.                     if ( e->flags & EF_NO_FADE )
  834.                         gr_setcolor( e->color );
  835.                     else
  836.                         gr_setcolor( gr_fade_table[e->color+256*8] );
  837.                     g3_draw_line( &Segment_points[e->moo.verts[0]], &Segment_points[e->moo.verts[1]] );
  838.                 }   else {
  839.                     DrawingListBright[nbright++] = e-Edges;
  840.                 }
  841.             }
  842.         }
  843.     }
  844.         
  845. // mprintf( (0, "Min distance=%.2f, ViewDist=%.2f, Delta=%.2f\n", f2fl(min_distance), f2fl(ViewDist), f2fl(min_distance)- f2fl(ViewDist) ));
  846.  
  847.     if ( min_distance < 0 ) min_distance = 0;
  848.  
  849.     // Sort the bright ones using a shell sort
  850.     {
  851.         int t;
  852.         int i, j, incr, v1, v2;
  853.     
  854.         incr = nbright / 2;
  855.         while( incr > 0 )   {
  856.             for (i=incr; i<nbright; i++ )   {
  857.                 j = i - incr;
  858.                 while (j>=0 )   {
  859.                     // compare element j and j+incr
  860.                     v1 = Edges[DrawingListBright[j]].moo.verts[0];
  861.                     v2 = Edges[DrawingListBright[j+incr]].moo.verts[0];
  862.  
  863.                     if (Segment_points[v1].p3_vec.z < Segment_points[v2].p3_vec.z) {
  864.                         // If not in correct order, them swap 'em
  865.                         t=DrawingListBright[j+incr];
  866.                         DrawingListBright[j+incr]=DrawingListBright[j];
  867.                         DrawingListBright[j]=t;
  868.                         j -= incr;
  869.                     }
  870.                     else
  871.                         break;
  872.                 }
  873.             }
  874.             incr = incr / 2;
  875.         }
  876.     }
  877.                     
  878.     // Draw the bright ones
  879.     for (i=0; i<nbright; i++ )  {
  880.         int color;
  881.         fix dist;
  882.         e = &Edges[DrawingListBright[i]];
  883.         p1 = &Segment_points[e->moo.verts[0]];
  884.         p2 = &Segment_points[e->moo.verts[1]];
  885.         dist = p1->p3_vec.z - min_distance;
  886.         // Make distance be 1.0 to 0.0, where 0.0 is 10 segments away;
  887.         if ( dist < 0 ) dist=0;
  888.         if ( dist >= Automap_farthest_dist ) continue;
  889.  
  890.         if ( e->flags & EF_NO_FADE )    {
  891.             gr_setcolor( e->color );
  892.         } else {
  893.             dist = F1_0 - fixdiv( dist, Automap_farthest_dist );
  894.             color = f2i( dist*31 );
  895.             gr_setcolor( gr_fade_table[e->color+color*256] );   
  896.         }
  897.         g3_draw_line( p1, p2 );
  898.     }
  899.  
  900. }
  901.  
  902.  
  903. //==================================================================
  904. //
  905. // All routines below here are used to build the Edge list
  906. //
  907. //==================================================================
  908.  
  909.  
  910. //finds edge, filling in edge_ptr. if found old edge, returns index, else return -1
  911. static int automap_find_edge(int v0,int v1,Edge_info **edge_ptr)
  912. {
  913.     long vv;
  914.     short hash,oldhash;
  915.     int ret;
  916.  
  917.     vv = (v1<<16) + v0;
  918.  
  919.     oldhash = hash = ((v0*5+v1) % Max_edges);
  920.  
  921.     ret = -1;
  922.  
  923.     while (ret==-1) {
  924.         if (Edges[hash].num_faces == 0 ) ret=0;
  925.         else if (Edges[hash].moo.vv == vv) ret=1;
  926.         else {
  927.             if (++hash==Max_edges) hash=0;
  928.             if (hash==oldhash) Error("Edge list full!");
  929.         }
  930.     }
  931.  
  932.     *edge_ptr = &Edges[hash];
  933.  
  934.     if (ret == 0)
  935.         return -1;
  936.     else
  937.         return hash;
  938.  
  939. }
  940.  
  941.  
  942. void add_one_edge( short va, short vb, ubyte color, ubyte side, short segnum, int hidden, int grate, int no_fade )  {
  943.     int found;
  944.     Edge_info *e;
  945.     short tmp;
  946.  
  947.     if ( Num_edges >= Max_edges)    {
  948.         // GET JOHN! (And tell him that his 
  949.         // MAX_EDGES_FROM_VERTS formula is hosed.)
  950.         // If he's not around, save the mine, 
  951.         // and send him  mail so he can look 
  952.         // at the mine later. Don't modify it.
  953.         // This is important if this happens.
  954.         Int3();     // LOOK ABOVE!!!!!!
  955.         automap_abort = 1;
  956.         return;
  957.     }
  958.  
  959.     if ( va > vb )  {
  960.         tmp = va;
  961.         va = vb;
  962.         vb = tmp;
  963.     }
  964.  
  965.     found = automap_find_edge(va,vb,&e);
  966.         
  967.     if (found == -1) {
  968.         e->moo.verts[0] = va;
  969.         e->moo.verts[1] = vb;
  970.         e->color = color;
  971.         e->num_faces = 1;
  972.         e->flags = EF_USED | EF_DEFINING;           // Assume a normal line
  973.         e->sides[0] = side;
  974.         e->segnum[0] = segnum;
  975.         //Edge_used_list[Num_edges] = e-Edges;
  976.         if ( (e-Edges) > Highest_edge_index )
  977.             Highest_edge_index = e - Edges;
  978.         Num_edges++;
  979.     } else {
  980.         //Assert(e->num_faces < 8 );
  981.  
  982.         if ( color != WALL_NORMAL_COLOR )
  983.             e->color = color;
  984.         if ( e->num_faces < 4 ) {
  985.             e->sides[e->num_faces] = side;                  
  986.             e->segnum[e->num_faces] = segnum;
  987.             e->num_faces++;
  988.         }
  989.     }
  990.  
  991.     if ( grate )
  992.         e->flags |= EF_GRATE;
  993.  
  994.     if ( hidden )
  995.         e->flags|=EF_SECRET;        // Mark this as a hidden edge
  996.     if ( no_fade )
  997.         e->flags |= EF_NO_FADE;
  998. }
  999.  
  1000. void add_one_unknown_edge( short va, short vb ) {
  1001.     int found;
  1002.     Edge_info *e;
  1003.     short tmp;
  1004.  
  1005.     if ( va > vb )  {
  1006.         tmp = va;
  1007.         va = vb;
  1008.         vb = tmp;
  1009.     }
  1010.  
  1011.     found = automap_find_edge(va,vb,&e);
  1012.     if (found != -1)    
  1013.         e->flags|=EF_FRONTIER;      // Mark as a border edge
  1014. }
  1015.  
  1016. extern obj_position Player_init[];
  1017.  
  1018. void add_segment_edges(segment *seg)
  1019. {
  1020.     int     is_grate, no_fade;
  1021.     ubyte   color;
  1022.     int sn;
  1023.     int segnum = seg-Segments;
  1024.     int hidden_flag;
  1025.     
  1026.     for (sn=0;sn<MAX_SIDES_PER_SEGMENT;sn++) {
  1027.         short   vertex_list[4];
  1028.  
  1029.         hidden_flag = 0;
  1030.  
  1031.         is_grate = 0;
  1032.         no_fade = 0;
  1033.  
  1034.         color = 255;
  1035.         if (seg->children[sn] == -1) {
  1036.             color = WALL_NORMAL_COLOR;
  1037.         }
  1038.  
  1039.         switch( seg->special )  {
  1040.         case SEGMENT_IS_FUELCEN:
  1041.             color = BM_XRGB( 29, 27, 13 );
  1042.             break;
  1043.         case SEGMENT_IS_CONTROLCEN:
  1044.             color = BM_XRGB( 29, 0, 0 );
  1045.             break;
  1046.         case SEGMENT_IS_ROBOTMAKER:
  1047.             color = BM_XRGB( 29, 0, 31 );
  1048.             break;
  1049.         }
  1050.  
  1051.         if (seg->sides[sn].wall_num > -1)   {
  1052.  
  1053.             switch( Walls[seg->sides[sn].wall_num].type )   {
  1054.             case WALL_DOOR:
  1055.                 if (Walls[seg->sides[sn].wall_num].keys == KEY_BLUE) {
  1056.                     no_fade = 1;
  1057.                     color = WALL_DOOR_BLUE;
  1058.                     //mprintf((0, "Seg %i, side %i has BLUE wall\n", segnum, sn));
  1059.                 } else if (Walls[seg->sides[sn].wall_num].keys == KEY_GOLD) {
  1060.                     no_fade = 1;
  1061.                     color = WALL_DOOR_GOLD;
  1062.                     //mprintf((0, "Seg %i, side %i has GOLD wall\n", segnum, sn));
  1063.                 } else if (Walls[seg->sides[sn].wall_num].keys == KEY_RED) {
  1064.                     no_fade = 1;
  1065.                     color = WALL_DOOR_RED;
  1066.                     //mprintf((0, "Seg %i, side %i has RED wall\n", segnum, sn));
  1067.                 } else if (!(WallAnims[Walls[seg->sides[sn].wall_num].clip_num].flags & WCF_HIDDEN)) {
  1068.                     int connected_seg = seg->children[sn];
  1069.                     if (connected_seg != -1) {
  1070.                         int connected_side = find_connect_side(seg, &Segments[connected_seg]);
  1071.                         int keytype = Walls[Segments[connected_seg].sides[connected_side].wall_num].keys;
  1072.                         if ((keytype != KEY_BLUE) && (keytype != KEY_GOLD) && (keytype != KEY_RED))
  1073.                             color = WALL_DOOR_COLOR;
  1074.                         else {
  1075.                             switch (Walls[Segments[connected_seg].sides[connected_side].wall_num].keys) {
  1076.                                 case KEY_BLUE:  color = WALL_DOOR_BLUE; no_fade = 1; break;
  1077.                                 case KEY_GOLD:  color = WALL_DOOR_GOLD; no_fade = 1; break;
  1078.                                 case KEY_RED:   color = WALL_DOOR_RED;  no_fade = 1; break;
  1079.                                 default:    Error("Inconsistent data.  Supposed to be a colored wall, but not blue, gold or red.\n");
  1080.                             }
  1081.                             //mprintf((0, "Seg %i, side %i has a colored door on the other side.\n", segnum, sn));
  1082.                         }
  1083.                     }
  1084.                 } else {
  1085.                     color = WALL_NORMAL_COLOR;
  1086.                     hidden_flag = 1;
  1087.                     //mprintf((0, "Wall at seg:side %i:%i is hidden.\n", seg-Segments, sn));
  1088.                 }
  1089.                 break;
  1090.             case WALL_CLOSED:
  1091.                 // Make grates draw properly
  1092.                 color = WALL_NORMAL_COLOR;
  1093.                 is_grate = 1;
  1094.                 break;
  1095.             case WALL_BLASTABLE:
  1096.                 // Hostage doors
  1097.                 color = WALL_DOOR_COLOR;    
  1098.                 break;
  1099.             }
  1100.         }
  1101.     
  1102.         if (segnum==Player_init[Player_num].segnum)
  1103.             color = BM_XRGB(31,0,31);
  1104.  
  1105.         if ( color != 255 ) {
  1106.             // If they have a map powerup, draw unvisited areas in dark blue.
  1107.             if (Players[Player_num].flags & PLAYER_FLAGS_MAP_ALL && (!Automap_visited[segnum])) 
  1108.                 color = BM_XRGB( 0, 0, 25 );
  1109.  
  1110.             get_side_verts(vertex_list,segnum,sn);
  1111.             add_one_edge( vertex_list[0], vertex_list[1], color, sn, segnum, hidden_flag, 0, no_fade );
  1112.             add_one_edge( vertex_list[1], vertex_list[2], color, sn, segnum, hidden_flag, 0, no_fade );
  1113.             add_one_edge( vertex_list[2], vertex_list[3], color, sn, segnum, hidden_flag, 0, no_fade );
  1114.             add_one_edge( vertex_list[3], vertex_list[0], color, sn, segnum, hidden_flag, 0, no_fade );
  1115.  
  1116.             if ( is_grate ) {
  1117.                 add_one_edge( vertex_list[0], vertex_list[2], color, sn, segnum, hidden_flag, 1, no_fade );
  1118.                 add_one_edge( vertex_list[1], vertex_list[3], color, sn, segnum, hidden_flag, 1, no_fade );
  1119.             }
  1120.         }
  1121.     }
  1122.  
  1123. }
  1124.  
  1125.  
  1126. // Adds all the edges from a segment we haven't visited yet.
  1127.  
  1128. void add_unknown_segment_edges(segment *seg)
  1129. {
  1130.     int sn;
  1131.     int segnum = seg-Segments;
  1132.     
  1133.     for (sn=0;sn<MAX_SIDES_PER_SEGMENT;sn++) {
  1134.         short   vertex_list[4];
  1135.  
  1136.         // Only add edges that have no children
  1137.         if (seg->children[sn] == -1) {
  1138.             get_side_verts(vertex_list,segnum,sn);
  1139.     
  1140.             add_one_unknown_edge( vertex_list[0], vertex_list[1] );
  1141.             add_one_unknown_edge( vertex_list[1], vertex_list[2] );
  1142.             add_one_unknown_edge( vertex_list[2], vertex_list[3] );
  1143.             add_one_unknown_edge( vertex_list[3], vertex_list[0] );
  1144.         }
  1145.  
  1146.  
  1147.     }
  1148.  
  1149. }
  1150.  
  1151. void automap_build_edge_list()
  1152. {   
  1153.     int i,e1,e2,s;
  1154.     Edge_info * e;
  1155.  
  1156.     Automap_cheat = 0;
  1157.  
  1158.     if ( Players[Player_num].flags & PLAYER_FLAGS_MAP_ALL_CHEAT )
  1159.         Automap_cheat = 1;      // Damn cheaters...
  1160.  
  1161.     // clear edge list
  1162.     for (i=0; i<Max_edges; i++) {
  1163.         Edges[i].num_faces = 0;
  1164.         Edges[i].flags = 0;
  1165.     }
  1166.     Num_edges = 0;
  1167.     Highest_edge_index = -1;
  1168.  
  1169.     if (Automap_cheat || (Players[Player_num].flags & PLAYER_FLAGS_MAP_ALL) )   {
  1170.         // Cheating, add all edges as visited
  1171.         for (s=0; s<=Highest_segment_index; s++)
  1172.             #ifdef EDITOR
  1173.             if (Segments[s].segnum != -1)
  1174.             #endif
  1175.             {
  1176.                 add_segment_edges(&Segments[s]);
  1177.             }
  1178.     } else {
  1179.         // Not cheating, add visited edges, and then unvisited edges
  1180.         for (s=0; s<=Highest_segment_index; s++)
  1181.             #ifdef EDITOR
  1182.             if (Segments[s].segnum != -1)
  1183.             #endif
  1184.                 if (Automap_visited[s]) {
  1185.                     add_segment_edges(&Segments[s]);
  1186.                 }
  1187.     
  1188.         for (s=0; s<=Highest_segment_index; s++)
  1189.             #ifdef EDITOR
  1190.             if (Segments[s].segnum != -1)
  1191.             #endif
  1192.                 if (!Automap_visited[s]) {
  1193.                     add_unknown_segment_edges(&Segments[s]);
  1194.                 }
  1195.     }
  1196.  
  1197.     // Find unnecessary lines (These are lines that don't have to be drawn because they have small curvature)
  1198.     for (i=0; i<=Highest_edge_index; i++ )  {
  1199.         e = &Edges[i];
  1200.         if (!(e->flags&EF_USED)) continue;
  1201.  
  1202.         for (e1=0; e1<e->num_faces; e1++ )  {
  1203.             for (e2=1; e2<e->num_faces; e2++ )  {
  1204.                 if ( (e1 != e2) && (e->segnum[e1] != e->segnum[e2]) )   {
  1205.                     #ifdef COMPACT_SEGS
  1206.                     vms_vector v1, v2;
  1207.                     get_side_normal(&Segments[e->segnum[e1]], e->sides[e1], 0, &v1 );
  1208.                     get_side_normal(&Segments[e->segnum[e2]], e->sides[e2], 0, &v2 );
  1209.                     if ( vm_vec_dot(&v1,&v2) > (F1_0-(F1_0/10))  )  {
  1210.                     #else
  1211.                     if ( vm_vec_dot( &Segments[e->segnum[e1]].sides[e->sides[e1]].normals[0], &Segments[e->segnum[e2]].sides[e->sides[e2]].normals[0] ) > (F1_0-(F1_0/10))  )   {
  1212.                     #endif
  1213.                         e->flags &= (~EF_DEFINING);
  1214.                         break;
  1215.                     }
  1216.                 }
  1217.             }
  1218.             if (!(e->flags & EF_DEFINING))
  1219.                 break;
  1220.         }
  1221.     }   
  1222.  
  1223.     mprintf( (0, "Automap used %d / %d edges\n", Num_edges, Max_edges  ));
  1224.  
  1225. }
  1226.